home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 501_600 / DISK0579 / DISK0579.ZIP / CHAP11.TXT < prev    next >
Text File  |  1989-12-01  |  27KB  |  591 lines

  1.  
  2.  
  3.  
  4.                                                    Chapter 11
  5.                                             FILE INPUT/OUTPUT
  6.  
  7.  
  8. FILES HANDLE SERIAL DATA
  9. ____________________________________________________________
  10.  
  11. One of the most common operations when using a computer is to
  12. either read from, or write to a file.  You are already
  13. somewhat experienced in file handling from the last chapter,
  14. because in computer terminology, the keyboard, terminal, and
  15. printer are all classified as files.  A file is any serial
  16. input or output device that the computer has access to.  Since
  17. it is serial, only one piece of information is available to
  18. the computer at any instant of time. This is in contrast to
  19. an array, for example, in which all elements of the array are
  20. stored internally and are all available at any time.
  21.  
  22.  
  23. A SHORT HISTORY LESSON
  24. ____________________________________________________________
  25.  
  26. Several years ago computers were all large cumbersome machines
  27. with large peripheral devices such as magnetic tape drives,
  28. punch card readers, paper tape readers or punches, etc.  It
  29. was a simple task to assign the paper tape reader a symbol and
  30. use that symbol whenever it was necessary to read a paper
  31. tape.  There was never more than one file on the paper tape
  32. being read, so it was simply read sequentially, and hopefully
  33. the data was the desired data.  With the advent of floppy
  34. disks, and hard disks, it became practical to put several
  35. files of data on one disk, none of which necessarily had
  36. anything to do with any of the other files on that disk.  This
  37. led to the problem of reading the proper file from the disk,
  38. not just reading the disk.
  39.  
  40. Pascal was originally released in 1971, before the
  41. introduction of the compact floppy disk.  The original release
  42. of Pascal had no provision for selecting a certain file from
  43. among the many included on the disk.  Each compiler writer had
  44. to overcome this deficiency and he did so by defining an
  45. extension to the standard Pascal system.  Unfortunately, all
  46. of the extensions were not the same, and there are now several
  47. ways to accomplish this operation.  There are primarily two
  48. ways, one using the Assign statement, and the other using the
  49. Open statement.  They are similar to each other and they
  50. accomplish the same end result.
  51.  
  52.  
  53. BACK TO THE PRESENT TIME
  54. ____________________________________________________________
  55.  
  56. All of the above was described to let you know that we will
  57. have a problem in this chapter, namely, how do we cover all
  58.  
  59.                                                     Page 11-1
  60.  
  61.                                             File Input/Output
  62.  
  63. of the possible implementations of Pascal available?  The
  64. answer is, we can't.  Most of what is covered in this chapter
  65. will apply to all compilers, and all that is covered will
  66. apply to the TURBO Pascal compilers, versions 3.0 through 5.x. 
  67. This tutorial is especially written for the TURBO Pascal
  68. compilers, but you should be warned you will find differences
  69. in Pascal implementations if you ever find a need to use a
  70. different Pascal compiler someday.  You may, for example, need
  71. to use a mini-computer or a mainframe computer someday to
  72. complete a programming assignment.  When that happens, you
  73. will find that the area of input/output control will probably
  74. be the biggest difference in the implementations of Pascal.
  75.  
  76.  
  77. READING AND DISPLAYING A FILE
  78. ____________________________________________________________
  79.  
  80. Examine the file READFILE.PAS for an         ================
  81. example of a program that can read a text      READFILE.PAS
  82. file from the disk.  In fact it will read    ================
  83. itself from the disk and display it on the
  84. video monitor.  The first statement in the
  85. program is the Assign statement.  This is TURBO Pascal's way
  86. of selecting which file on the disk will be either read from
  87. or written to.  In this case we will read from the disk.  The
  88. first argument in the Assign statement is the device specifier
  89. similar to Lst used in the last chapter for the printer.  We
  90. have chosen to use the name Turkey for the device identifier,
  91. but could have used any valid identifier.  This identifier
  92. must be defined in a var declaration as a TEXT type variable. 
  93. The next argument is the filename desired.  The filename can
  94. be defined as a string constant, as it is here, or as a string
  95. variable.
  96.  
  97. The TEXT type is a predefined type and is used to define a
  98. file identifier.  It is predefined as a "file of char", so it
  99. can only be used for a text file.  We will see later that
  100. there is another type of file, a binary file.
  101.  
  102. Now that we have a file identified, it is necessary to prepare
  103. it for reading by executing a reset statement in line 9.  The
  104. Reset statement positions the read pointer at the beginning
  105. of the file, ready to read the first piece of information in
  106. the file.  Once we have done that, data is read from the file
  107. in the same manner as it was when reading from the keyboard. 
  108. In this program, the input is controlled by the while loop
  109. which is executed until we exhaust the data in the file.
  110.  
  111.  
  112. WHAT ARE THE "EOF" AND "EOLN" FUNCTIONS?
  113. ____________________________________________________________
  114.  
  115. The Eof function is new and must be defined.  When we read
  116. data from the file, we move closer and closer to the end,
  117.  
  118.                                                     Page 11-2
  119.  
  120.                                             File Input/Output
  121.  
  122. until finally we reach the end and there is no more data to
  123. read.  This is called "end of file" and is abbreviated Eof. 
  124. Pascal has this function available as a part of the standard
  125. library which returns FALSE until we reach the last line of
  126. the file.  When there is no more data to read left in the
  127. file, the function Eof returns TRUE.  To use the function, we
  128. merely give it our file identifier as an argument.  It should
  129. be clear to you that we will loop in this program until we
  130. read all of the data available in the input file.
  131.  
  132. The Eoln function is not used in this program but is a very
  133. useful function.  If the input pointer is anywhere in the text
  134. file except at the end of a line, the Eoln returns FALSE, but
  135. at the end of a line, it returns a value of TRUE.  This
  136. function can therefore be used to find the end of a line of
  137. text for variable length text input.
  138.  
  139. To actually read the data, we use the Readln procedure, giving
  140. it our identifier Turkey and the name of the variable we want
  141. the data read into.  In this case, we read up to 80 characters
  142. into the string and if more are available, ignore them.  You
  143. should remember when we did this in the last chapter from the
  144. keyboard input.  We are using the same technique here except
  145. we are reading from a file this time.  Since we would like to
  146. do something with the data, we output the line to the default
  147. device, the video monitor.  It should be clear to you by now
  148. that the program will read the entire file and display it on
  149. the monitor.
  150.  
  151. Finally, we Close the file Turkey.  It is not really necessary
  152. to close the file because the system will close it for you
  153. automatically at program termination, but it is a good habit
  154. to get into.  It must be carefully pointed out here, that you
  155. did not do anything to the input file, you only read it and
  156. left it intact.  You could Reset it and reread it again in
  157. this same program.  Compile and run this program to see if it
  158. does what you expect it to do.
  159.  
  160.  
  161. A PROGRAM TO READ ANY FILE
  162. ____________________________________________________________
  163.  
  164. Examine the next program READDISP.PAS for    ================
  165. an improved file reading program.  This is     READDISP.PAS
  166. very similar except that it asks you for     ================
  167. the name of the file that you wish to
  168. display, and enters the name into a 12
  169. character string named Name_Of_File_To_Input.  This is then
  170. used in the Assign statement to select the file to be read,
  171. and the file is reset as before.  Lines 15 through 18 display
  172. a header, and from that point on, the program is identical to
  173. the last one with a few small additions.  In order to
  174. demonstrate the use of a function within the Writeln
  175. specification, the program calls for the length of the input
  176.  
  177.                                                     Page 11-3
  178.  
  179.                                             File Input/Output
  180.  
  181. string in line 23 and displays it before each line.  The lines
  182. are counted as they are read and displayed, and the line count
  183. is displayed at the end of the listing.  
  184.  
  185. You should be able to see clearly how each of these operations
  186. is accomplished.  Compile and run this program, entering any
  187. filename we have used so far (be sure to include the .PAS
  188. extension).  After a successful run, enter a nonexistent
  189. filename and see the I/O error.
  190.  
  191.  
  192. HOW TO COPY A FILE (SORT OF)
  193. ____________________________________________________________
  194.  
  195. Examine the file READSTOR.PAS for an         ================
  196. example of reading from a file and writing     READSTOR.PAS
  197. to another one.  In this program we          ================
  198. request an operator input for the filename
  199. to read, after which we Assign the name to
  200. the file and Reset it.  When we reset the file however, we go
  201. to a bit of extra trouble to assure that the file actually
  202. exists.  
  203.  
  204. Suppose we input a filename, and the file did not exist
  205. because the file was actually missing, or because we entered
  206. the filename wrong.  Without the extra effort, the TURBO
  207. Pascal runtime system would indicate a run-time error, and
  208. terminate the program returning us to the operating system. 
  209. In order to make a program easier to use, it would be nice to
  210. tell the operator that the file didn't exist and give him the
  211. opportunity to try again with another file name.  The method
  212. given in lines 16 through 20 of this program will allow you
  213. to do just that.
  214.  
  215.  
  216. USING A COMPILER DIRECTIVE
  217. ____________________________________________________________
  218.  
  219. First you must disable the built in TURBO Pascal I/O checking
  220. by inserting the compiler directive in line 16.  This tells
  221. the system to ignore any I/O errors from this point on and if
  222. the file doesn't exist, the system will not abort when you
  223. attempt to reset it in line 17.  Another compiler directive
  224. is given in line 18 to enable I/O checking again for the
  225. remainder of the program.  
  226.  
  227.  
  228. WE DO OUR OWN FILE CHECKING
  229. ____________________________________________________________
  230.  
  231. If the file didn't exist and could not therefore be reset, we
  232. have a problem because the program thinks the file is
  233. available for use but it actually isn't.  Fortunately, TURBO
  234. Pascal has a built in variable, named IOResult, that informs
  235.  
  236.                                                     Page 11-4
  237.  
  238.                                             File Input/Output
  239.  
  240. us of the result of each I/O operation.  Following any I/O
  241. operation, if this variable contains the value of zero, the
  242. I/O operation was correct, and if it contains any other value,
  243. the operation had some sort of error.  In our case, we simply
  244. compare it to zero to generate a boolean value, then based on
  245. the boolean value we either give an error message and stop,
  246. or perform the desired file operations.
  247.  
  248. It would be good programming practice to check all file
  249. openings in this manner to allow the operator to recover from
  250. a simple oversight or spelling error.
  251.  
  252. If the file was opened properly, then in line 21 through 24
  253. we request a different filename to write to, which is assigned
  254. to a different identifier.  Note that the output file is not
  255. checked for a valid opening as it should be.  The statement
  256. in line 24 is new to us, the Rewrite statement.  This name
  257. apparently comes from the words REset for WRITEing because
  258. that is exactly what it does.  It clears the entire file of
  259. any prior data and prepares to write into the very beginning
  260. of the file.  Each time you write into it, the file grows by
  261. the amount of the new data written.
  262.  
  263. Once the identifier has been defined, and the Rewrite has been
  264. executed, writing to the file is identical to writing to the
  265. display with the addition of the identifier being specified
  266. prior to the first output field.  With that in mind, you
  267. should have no trouble comprehending the operation of the
  268. program.  This program is very similar to the last, except
  269. that it numbers the lines as the file is copied.  After
  270. running the program, look in your default directory for the
  271. new filename which you input when it asked for the output
  272. filename.  Examine that file to see if it is truly a copy of
  273. the input file with line numbers added.  
  274.  
  275. One word of caution.  If you used an existing filename for the
  276. output file, the file was overwritten, and the original
  277. destroyed.  In that case, it was good that you followed
  278. instructions at the beginning of this tutorial and made a
  279. working copy of the distribution disk.  You did do that,
  280. didn't you?
  281.  
  282. Compile and run this program two different ways, once with a
  283. valid input filename that should run properly, and the second
  284. time with an input filename that doesn't exist to prove to
  285. yourself that the test actually does work correctly.
  286.  
  287.  
  288. HOW TO READ INTEGER DATA FROM A FILE
  289. ____________________________________________________________
  290.  
  291. It is well and good to be able to read text from a file, but
  292. now we would like to read other forms of data from a file. 
  293. First we will look at an example program to read data from a
  294.  
  295.                                                     Page 11-5
  296.  
  297.                                             File Input/Output
  298.  
  299. text file, then later we will see an example program that
  300. reads from a binary file.  
  301.  
  302. Examine the program READINTS.PAS for an      ================
  303. example of reading data from a text file.      READINTS.PAS
  304. A text file is an ASCII file that can be     ================
  305. read by a text editor, printed, displayed,
  306. or in some cases, compiled and executed. 
  307. It is simply a file made up of a long string of char type
  308. data, and usually includes linefeeds, carriage returns, and
  309. blanks for neat formatting.  Nearly every file on the Tutorial
  310. disk you received with this package is a text file.  One
  311. notable exception is the file named LIST.EXE, which is an
  312. executable program file.
  313.  
  314. The example program has nothing new, you have seen everything
  315. in it before.  We have an assignment, followed by a reset of
  316. our file, followed by four read and write loops.  Each of the
  317. loops has a subtle difference to illustrate the Read and
  318. Readln statements.  Notice that the same file is used for
  319. reading four times with a Reset prior to each, illustrating
  320. the nondestructive read mentioned a few paragraphs ago.
  321.  
  322. The file we will be using is named INTDATA.TXT and is on your
  323. disk.  You could display it at this time using the program
  324. READDISP.PAS we covered recently.  Notice that it is simply
  325. composed of the integer values from 101 to 148 arranged four
  326. to a line with a couple of spaces between each for separation
  327. and a neat appearance.  The important thing to remember is
  328. that there are four data points per line.
  329.  
  330.  
  331.  
  332. READ AND READLN ARE SLIGHTLY DIFFERENT
  333. ____________________________________________________________
  334.  
  335. As variables are read in with either procedure, the input file
  336. is scanned for the variables using blanks as delimiters.  If
  337. there are not enough data points on one line to satisfy the
  338. arguments in the input list, the next line is searched also,
  339. and the next, etc.  Finally when all of the arguments in the
  340. input list are satisfied, the Read is complete, but the Readln
  341. is not.  If it is a Read procedure, the input pointer is left
  342. at that point in the file, but if it is a Readln procedure,
  343. the input pointer is advanced to the beginning of the next
  344. line.  The next paragraph should clear that up for you.
  345.  
  346. The input data file INTDATA.TXT has four data points per line
  347. but the first loop in the program READINTS.PAS requests only
  348. three each time through the loop.  The first time through, it
  349. reads the values 101, 102, and 103, and displays those values,
  350. leaving the input pointer just prior to the 104, because it
  351. is a Read procedure.  The next time through, it reads the
  352. value 104, advances to the next line and reads the values 105,
  353.  
  354.                                                     Page 11-6
  355.  
  356.                                             File Input/Output
  357.  
  358. and 106, leaving the pointer just prior to the 107.  This
  359. continues until the 5 passes through the loop are completed.
  360.  
  361. The loop in lines 19 through 22 contains a Readln procedure
  362. and also reads the values 101, 102, and 103, but when the
  363. input parameter list is satisfied, it moves the pointer to the
  364. beginning of the next line, leaving it just before the 105. 
  365. The values are printed out and the next time we come to the
  366. Readln, we read the 105, 106, and 107, and the pointer is
  367. moved to the beginning of the next line.  It would be good to
  368. run the program now to see the difference in output data for
  369. the two loops.  Remember that the only difference is that the
  370. first loop uses the Read procedure, and the second uses the
  371. Readln procedure.
  372.  
  373. When you come back to the program again, observe the last two
  374. loops, which operate much like the first two except that there
  375. are now five requested integer variables, and the input file
  376. still only has four per line.  This is no problem.  Both input
  377. procedures will simply read the first four in the first line,
  378. advance to the second line for its required fifth input, and
  379. each will do its own operation next.  The Read procedure will
  380. leave the input pointer just before the second data point of
  381. the second line, and the Readln will advance the input pointer
  382. to the beginning of the third line.  Run this program and
  383. observe the four output fields to see an illustration of these
  384. principles.
  385.  
  386.  
  387. NOW TO READ SOME REAL VARIABLES FROM A FILE
  388. ____________________________________________________________
  389.  
  390. Examine the file named REALDATA.TXT supplied on your Pascal
  391. Tutorial disk.  You will see 8 lines of what appears to be
  392. scrambled data, but it is good data that Pascal can read. 
  393. Notice especially line 4 which has some data missing, and line
  394. 6 which has some extra data.
  395.  
  396. Examine the program file READDATA.PAS        ================
  397. which will be used to illustrate the           READDATA.PAS
  398. method of reading real type data.            ================
  399. Everything should be familiar to you,
  400. since there is nothing new here.  The
  401. Readln statement is requesting one integer variable, and three
  402. real variables, which is what most of the input file
  403. contained.  When we come to the fourth line, there are not
  404. enough data points available, so the first two data points of
  405. the next line are read to complete the fourth pass through the
  406. loop.  Since the file pointer is advanced to the beginning of
  407. the next line, we are automatically synchronized with the data
  408. again.  When we come to the sixth line, the last two data
  409. points are simply ignored.  Run the program to see if the
  410. results are as you would predict.
  411.  
  412.  
  413.                                                     Page 11-7
  414.  
  415.                                             File Input/Output
  416.  
  417. If a Read were substituted for the Readln in line 14 of the
  418. program, the file pointer would not be advanced to the
  419. beginning of line 6 after the fourth pass through the loop. 
  420. The next attempt to read would result in trying to read the
  421. value 0.0006 as an integer, and a run time error would result. 
  422. Modify the program, substituting a Read for the Readln in line
  423. 14, and see if this is not true.
  424.  
  425. It should be pointed out that TURBO Pascal 4.0 and 5.x both
  426. require a digit both before and after the decimal point in all
  427. data that is to be read in as real type data or it will be
  428. flagged as a run-time error and the program will be halted. 
  429. The digits can be zero as they are in several places in the
  430. example file but they must be there.  If you are using TURBO
  431. Pascal 3.0, the leading and trailing digits are not required.
  432.  
  433. That is all there is to reading and writing text files.  If
  434. you learn the necessities, you will not be stumbling around
  435. in the area of input/output which is very intimidating to many
  436. people.  Remember to Assign, then Reset before reading,
  437. Rewrite before writing, and Close before quitting.  It is of
  438. the utmost importance to close a file you have been writing
  439. to before quitting to write the last few buffers to the file,
  440. but it is not as important to close read files unless you are
  441. using a lot of them, as there is an implementation dependent
  442. limit of how many files can be open at once.  It is possible
  443. to read from a file, close it, reopen it, and write to it in
  444. one program.  You can reuse a file as often as you desire in
  445. a program, but you cannot read from and write into a file at
  446. the same time.
  447.  
  448.  
  449. NOW FOR BINARY INPUT AND OUTPUT
  450. ____________________________________________________________
  451.  
  452. Examine the file BINOUT.PAS for an example   ================
  453. of writing data to a file in binary form.       BINOUT.PAS
  454. First there is a record defined in the       ================
  455. type declaration part composed of three
  456. different variable types.  In the var
  457. part, Output_File is defined as a "file of Dat_Rec", the
  458. record defined earlier.  The variable Dog_Food is then defined
  459. as an array of the record, and a simple variable is defined.
  460.  
  461. Any file assigned a type of TEXT, which is a "file of char",
  462. is a text file.  A text file can be read and modified with a
  463. text editor, printed out, displayed on the monitor, etc. If
  464. a file is defined with any other definition, it will be a
  465. binary file and will be in an internal format as defined by
  466. the Pascal compiler and may not be readable by any compiler
  467. other than the one used to write it.  Attempting to display
  468. such a file will result in very strange looking gibberish on
  469. the monitor.
  470.  
  471.  
  472.                                                     Page 11-8
  473.  
  474.                                             File Input/Output
  475.  
  476. When we get to the program, the output file is assigned a name
  477. in line 15, and a Rewrite is performed on it to reset the
  478. input pointer to the beginning of the file, empty the file,
  479. and prepare for writing data into it.  The loop in lines 18
  480. through 22 simply assigns nonsense data to all of the
  481. variables in the 20 records so we have something to work with.
  482.  
  483. We write a message to the display that we are ready to start
  484. outputting data, then we output the data one record at a time
  485. with the standard Write statement.  A few cautions are in
  486. order here.  The output file can be defined to store any
  487. simple variable type, integer, byte, real, or a record, but
  488. the types cannot be mixed.  The record itself however, can be
  489. any combination of data including other records if desired,
  490. but any file can only have one type of record written to it. 
  491.  
  492. A Writeln statement is illegal when writing to a binary file
  493. because a binary file is not line oriented.  A Write statement
  494. is limited to one output field per statement.  This is not a
  495. serious limitation since it is a simple matter to put one
  496. Write statement in the program for each variable you wish to
  497. write out to the file.  It is important to Close the file when
  498. you are finished writing to it.
  499.  
  500.  
  501. WHY USE A BINARY FILE
  502. ____________________________________________________________
  503.  
  504. A binary file written by a Pascal program cannot be read by
  505. a word processor, a text editor or any other application
  506. program such as a database or spreadsheet, and it may not even
  507. be readable by a Pascal program compiled by a different
  508. companies compiler because the actual data structure is
  509. implementation dependent.  It can't even be read by a Pascal
  510. program using the same compiler unless the data structure is
  511. identical to the one used to write the file.  With all these
  512. rules, it seems like a silly way to output data, but there are
  513. advantages to using a binary output.
  514.  
  515. A binary file uses less file space than a corresponding text
  516. file because the data is stored in a packed mode.  Since all
  517. significant digits of real data are stored, it is more precise
  518. unless you are careful to output all significant data to the
  519. corresponding TEXT file.  Finally, since the binary data does
  520. not require formatting into ASCII characters, it will be
  521. considerably faster than outputting it in TEXT format.  When
  522. you run this example program, it will create the file
  523. KIBBLES.BIT, and put 20 records in it.  Return to DOS and look
  524. for this file and verify its existence.  If you try to TYPE
  525. it, using the DOS TYPE command, you will have a real mess on
  526. your monitor because it does not contain char type data, but
  527. that might be a good exercise.
  528.  
  529.  
  530.  
  531.                                                     Page 11-9
  532.  
  533.                                             File Input/Output
  534.  
  535. READING A BINARY FILE
  536. ____________________________________________________________
  537.  
  538. BININ.PAS is another example program that   =================
  539. will read in the file we just created.          BININ.PAS
  540. Notice that the variables are named         =================
  541. differently, but the types are all
  542. identical to those used to write the file
  543. and they are in the same order.  An additional line is found
  544. in the program, the if statement.  We must check for the "end
  545. of file" marker to stop reading when we find it or Pascal will
  546. list an error and terminate operation.  Three pieces of
  547. information are written out to verify that we actually did
  548. read the data file in.
  549.  
  550. Once again, a few rules are in order.  A Readln is illegal
  551. since there are no lines in a binary file, and only one
  552. variable or record can be read in with each Read statement.
  553.  
  554.  
  555. FILE POINTERS, GET, AND PUT STATEMENTS
  556. ____________________________________________________________
  557.  
  558. File pointers and the Get and Put procedures are a part of
  559. standard Pascal, but since they are redundant and therefore
  560. not needed, they are not a part of TURBO Pascal.  The standard
  561. Read and Write procedures are more flexible, more efficient,
  562. and easier to use.  The use of Get and Put will not be
  563. illustrated or defined here.  If you ever have any need for
  564. them, they should be covered in detail in your Pascal
  565. reference manual for the particular implementation you are
  566. using.
  567.  
  568. Pointers will be covered in detail in the next chapter of this
  569. tutorial.
  570.  
  571.  
  572. PROGRAMMING EXERCISES
  573. ____________________________________________________________
  574.  
  575. 1.   Modify READFILE.PAS so that after reading and displaying
  576.      the file, the file is reset, then read and displayed
  577.      again.  This was suggested in the text.
  578.  
  579. 2.   Write a program to read the data from any text file, and
  580.      display it on the monitor with line numbers and the
  581.      number of characters in each line. Finally display the
  582.      number of lines found in the file, and the total number
  583.      of characters in the entire file. Compare this number
  584.      with the filesize given by the DOS command DIR.
  585.  
  586.  
  587.  
  588.  
  589.  
  590.                                                    Page 11-10
  591.